美团一面:知道MySQL的WAL、LSN、Checkpoint 吗?
在疯狂创客圈 的社群面试交流中,小伙伴在美团面试中, 遇到下面的问题:
知道MySQL的WAL、LSN、checkpoint吗?简单说说底层原理
现在把这个 题目以及参考答案,收入咱们的 《尼恩Java面试宝典》V41版,
供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
1. WAL (预写式日志)技术
WAL的全称是 Write-Ahead Logging。
修改的数据要持久化到磁盘,会先写入磁盘的文件系统缓存,然后可以由后台线程异步慢慢地刷回到磁盘。所以WAL技术修改数据需要写两次磁盘。
1.1 两次磁盘写
从内存到磁盘文件系统缓存,顺序IO
从文件系统缓存持久化到磁盘,随机IO
1.2 WAL的好处
节省了随机写磁盘的 IO 消耗(转成顺序写)。
2. LSN(日志序列号)
LSN是Log Sequence Number的缩写,即日志序列号,表示Redo Log 的序号。
2.1 特性
LSN占用8字节,LSN的值会随着日志的写入而逐渐增大,每写入一个 Redo Log 时,LSN 就会递增该 Redo Log 写入的字节数。
2.2 LSN的不同含义
重做日志写入的总量,单位字节。
通过 LSN 开始号码和结束号码可以计算出写入的日志量。
checkpoint的位置
最近一次刷盘的页,即最近一次检查点(checkpoint),也是通过LSN来记录的,它也会被写入redo log里。
数据页的版本号。
在每个页的头部,有一个FIL_PAGE_LSN,记录的该页的LSN。表示该页最后刷新时LSN的大小。
其可以用来标记数据页的“版本号”。因此页中的LSN用来判断页是否需要进行恢复操作。
通过数据页中的 LSN 值和redo log中的 LSN 值比较,如果页中的 LSN 值小于redo log中 LSN 值,则表示数据丢失了一部分,这时候可以通过redo log的记录来恢复到redo log中记录的 LSN 值时的状态。
2.3 查看LSN
redo log的LSN信息可以通过 show engine innodb status 命令来查看。
---
LOG
---
Log sequence number 15114138
Log flushed up to 15114138
Pages flushed up to 15114138
Last checkpoint at 15114129
0 pending log flushes, 0 pending chkp writes
10 log i/o's done, 0.00 log i/o's/second
其中:
log sequence number就是当前的redo log(in buffer)中的lsn; log flushed up to是刷到redo log file on disk中的lsn; pages flushed up to是已经刷到磁盘数据页上的LSN; last checkpoint at是上一次检查点所在位置的LSN。
3. Checkpoint(检查点)
3.1 背景
缓冲池的容量和重做日志(redo log)容量是有限的。
3.2 目的
Checkpoint所做的事就是把脏页给刷新回磁盘。
3.3 定义
一个时间点,由一个LSN值(Checkpoint LSN)表示的整型值,在checkpoint LSN之前的每个数据页(buffer pool中的脏页)的更改都已经落盘(刷新到数据文件中),checkpoint 完成后,在checkpoint LSN之前的Redo Log就不再需要了。
所以:checkpoint是通过LSN实现的。
3.4 分类
Sharp Checkpont
该机制下,在数据库发生关闭时将所有的脏页都刷新回磁盘。
Fuzzy Checkpoint
在该机制下,只刷新一部分脏页,而不是刷新所有脏页回磁盘。
数据库关闭时,使用 Sharp Checkpont 机制刷新脏页。
数据库运行时,使用 Fuzzy Checkpoint 机制刷新脏页。
3.5 检查点触发时机
Master Thread Checkpoint
后台异步线程以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘。
FLUSH_LRU_LIST Checkpoint
为了保证LRU列表中可用页的数量(通过参数innodb_lru_scan_depth控制,默认值1024),后台线程定期检测LRU列表中空闲列表的数量,若不满足,就会将移除LRU列表尾端的页,若移除的页为脏页,则需要进行Checkpoint。
show VARIABLES like 'innodb_lru_scan_depth'
Async/sync Flush Checkpoint
当重做日志不可用(即redo log写满)时,需要强制将一些页刷新回磁盘,此时脏页从脏页列表中获取。
Dirty Page too much Checkpoint
即脏页数量太多,会强制推进CheckPoint。目的是保证缓冲区有足够的空闲页。innodb_max_dirty_pages_pct的默认值为75,表示当缓冲池脏页比例达到该值时,就会强制进行Checkpoint,刷新一部分脏页到磁盘。
show VARIABLES like 'innodb_max_dirty_pages_pct'
3.6 解决的问题
缩短数据库的恢复时间。 缓冲池不够用时,刷新脏页到磁盘。 重做日志满时,刷新脏页。
4. LSN与checkpoint的联系
LSN号串联起一个事务开始到恢复的过程。
重启 innodb 时,Redo log 完不完整,采用 Redo log 相关知识。用 Redo log 恢复,启动数据库时,InnoDB 会扫描数据磁盘的数据页 data disk lsn 和日志磁盘中的 checkpoint lsn。
两者相等则从 checkpoint lsn 点开始恢复,恢复过程是利用 redo log 到 buffer pool,直到 checkpoint lsn 等于 redo log file lsn,则恢复完成。如果 checkpoint lsn 小于 data disk lsn,说明在检查点触发后还没结束刷盘时数据库宕机了。
因为 checkpoint lsn 最新值是在数据刷盘结束后才记录的,检查点之后有一部分数据已经刷入数据磁盘,这个时候数据磁盘已经写入部分的部分恢复将不会重做,直接跳到没有恢复的 lsn 值开始恢复。
5. 总结
日志空间中的每条日志对应一个LSN值,而在数据页的头部也记录了当前页最后一次修改的LSN号,每次当数据页刷新到磁盘后,会去更新日志文件中checkpoint,以减少需要恢复执行的日志记录。
极端情况下,数据页刷新到磁盘成功后,去更新checkpoint时如果宕机,则在恢复过程中,由于checkpoint还未更新,则数据页中的记录相当于被重复执行,不过由于在日志文件中的操作记录具有幂等性,所以同一条redo log执行多次,不影响数据的恢复。
End
此真题面试题,收录于《尼恩Java面试宝典》V41
硬核面试题推荐
硬核文章推荐
硬核电子书
👍《尼恩Java面试宝典》(极致经典,不断升级)全网下载超过300万次
👍尼恩Java高并发三部曲:全网下载超过200万次
👍《Java高并发核心编程-卷1(加强版)》,不断升级
👍《Java高并发核心编程-卷2(加强版)》,不断升级
👍《Java高并发核心编程-卷3(加强版)》,不断升级
👍《顶级3高架构行业案例 + 尼恩架构笔记 》N 篇+,不断添加
👍100份简历模板